import { defineStore } from "pinia";
import type { RouteRecordRaw } from "vue-router";
import router from "@/routers/index";
import { staticRouter } from "@/routers/modules/staticRouter";
import { type MenuItem } from "@/types/route";
import * as Api from "@/api/modules/user";
import * as Helpers from "@/routers/helpers/routeHelper";

export default defineStore("useMenuStore", {
  state: (): useMenuStore => {
    return {
      // 全部菜单树（后端返回）
      allMenuTree: [],
      // 顶部导航模块
      topMenuList: [],
      // 当前模块ID
      currentTopMenuId: null,
      // 当前内侧菜单
      sidebarMenuList: [],
      // 静态菜单
      staticMenu: [],
      // 按钮权限列表
      buttonPermissions: []
    };
  },
  getters: {
    getButtonPermissions(): Set<string> {
      return new Set(this.buttonPermissions);
    }
  },
  actions: {
    // 获取所有菜单
    async getAllMenuTree(isRefresh?: string) {
      const { data } = await Api.getMenu();
      if (!data.menu_list) return;

      this.allMenuTree = data.menu_list;
      this.buttonPermissions = data.btn_list;

      this.getStaticRouter();
      this.initMenuTree(isRefresh);
    },
    // 初始化路由
    initMenuTree(isRefresh?: string) {
      Helpers.buildDynamicRoutes(this.allMenuTree, this.topMenuList);
      const sessionId = JSON.parse(sessionStorage.getItem("currentTopMenuId"));

      // 如果缓存里没有ID，则默认取第一个
      const topId = !isRefresh ? this.topMenuList[0].id : (sessionId?.currentTopMenuId ?? this.topMenuList[0].id);

      if (topId) {
        this.setTopMenuId(topId);
      }
    },
    // 切换顶级菜单
    setTopMenuId(topId: number) {
      const currentTopMenu = this.topMenuList.find(item => item.id === topId)?.children || [];
      if (!currentTopMenu.length) return;

      this.currentTopMenuId = topId;
      const filteredMenuList = Helpers.filterVisibleMenus(currentTopMenu);
      this.sidebarMenuList = [...this.staticMenu, ...filteredMenuList];

      // 添加路由
      this.addRouters(currentTopMenu);
      // 有静态菜单 默认跳转第一个路由; 没有静态菜单 匹配动态路由中第一个有效子路由
      const topMenu = this.staticMenu.length ? this.staticMenu[0].path : Helpers.findFirstValidPath(this.sidebarMenuList);
      if (topMenu) return router.push(topMenu);
    },
    // 动态注册路由
    addRouters() {
      this.sidebarMenuList.forEach((route: MenuItem) => {
        // 避免重复注册（可加判断缓存）
        const already = router.hasRoute(route.name!);
        // 判断路由是否已经存在
        if (!already) {
          if (route.meta.is_large_screen == 1) {
            router.addRoute(route as unknown as RouteRecordRaw);
          } else {
            router.addRoute("layout", route as unknown as RouteRecordRaw);
          }
        }
      });
    },
    // 获取静态路由
    getStaticRouter() {
      if (!staticRouter.length) return;
      this.staticMenu = Helpers.filterVisibleMenus(staticRouter as unknown as MenuItem[]);
    },
    // 重置路由
    resetDynamicRoutes() {
      // 移除动态注册的 sidebar 路由
      this.sidebarMenuList.forEach(route => {
        if (router.hasRoute(route.name)) {
          router.removeRoute(route.name);
        }
      });

      // 清空菜单状态
      this.sidebarMenuList = [];
      this.topMenuList = [];
      this.currentTopMenuId = 0;
    },
    // 按钮权限
    hasPermission(
      codes: string | string[],
      mode: "some" | "every" = "some" // 'some' 至少一个，'every' 全部
    ): boolean {
      if (typeof codes === "string") {
        return this.getButtonPermissions.has(codes);
      }

      if (Array.isArray(codes)) {
        if (mode === "every") {
          return codes.every(code => this.getButtonPermissions.has(code));
        }
        return codes.some(code => this.getButtonPermissions.has(code));
      }

      return false;
    }
  },
  persist: [
    {
      key: "currentTopMenuId",
      storage: sessionStorage,
      pick: ["currentTopMenuId"]
    },
    {
      key: "buttonPermissions",
      storage: sessionStorage,
      pick: ["buttonPermissions"]
    }
  ]
});

export type useMenuStore = {
  allMenuTree: MenuItem[];
  topMenuList: MenuItem[];
  currentTopMenuId: number | null;
  sidebarMenuList: MenuItem[];
  staticMenu: MenuItem[];
  buttonPermissions: string[];
};
